﻿/*
   Copyright 2013 Dmitry Bratus

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Flower.Client;
using Flower.Services;
using Flower.Services.Data;
using System.Transactions;
using Flower.Logging;

namespace Flower.Processing
{
    internal class PassThroughStateService : IStateService
    {
        private static readonly Log Log = LogManager.CreateLog(typeof(PassThroughStateService).Name);

        private const int GetLatestStateTriesCount = 3;
        private static readonly TimeSpan GetLatestStateTransactionTimeout = TimeSpan.FromSeconds(15);

        private readonly IFlowerClient _flowerClient;

        public PassThroughStateService(IFlowerClient directory)
        {
            _flowerClient = directory;
        }

        public Guid Save(string pid, Blob state, bool isKeyState)
        {
            var stateId = Guid.NewGuid();

            _flowerClient
                .CreateScript()
                .SetText("@SaveState")
                .AddParameter("pid", pid)
                .AddParameter("state", MakeStateDirectoryEntry(state, stateId))
                .Execute();

            return stateId;
        }

        public ProcessState GetLatestState(string pid)
        {
            IList<DirectoryEntry> states = 
                _flowerClient.Directory.GetChildren
                (
                    pid,
                    DirectoryEntryTypes.State,
                    SortProperty.Default,
                    SortOrder.Desc,
                    0,
                    1
                );

            return
                states != null && states.Count > 0 ?
                    new ProcessState
                    {
                        Id = Guid.Parse(states[0].Name),
                        Data = ((State)states[0]).Data
                    } :
                    null;
        }

        public void MarkLatestStateAsKeyState(string pid)
        {
            // Do nothing.
        }

        public void MarkLatestStateAsFinalState(string pid)
        {
            // Do nothing.
        }

        private static State MakeStateDirectoryEntry(Blob data, Guid stateId)
        {
            if (data == null) throw new ArgumentNullException("data");

            return new State
            {
                Data = data,
                Name = stateId.ToString()
            };
        }
    }
}
